#ifndef EDGE_HPP
#define EDGE_HPP

#include "meshTypes_fwd.hpp"
#include "edgeBase.hpp"

namespace hms
{

template<>
class EdgeTraits<Edge>
{
public:
	using MeshType      = Mesh;
	using VertexIndices = Array2Xi::ConstColXpr;
	using CellIndices   = Array2Xi::ConstColXpr;
	using NormalVector  = Matrix2Xs::ConstColXpr;
};

/**
 * @brief Edge type for Mesh
 * 
 * Thin wrapper class which allows to access edge properties in a
 * more intuitive fashion, i.e. mesh.edge(2).length() instead of 
 * mesh.edges().length(2). With optimisation level 2 or higher, the performance
 * impact should be zero.
 */
class Edge : public EdgeBase<Edge>
{
public:
	using Traits = EdgeTraits<Edge>;
	using NormalVector  = Traits::NormalVector;
	using VertexIndices = Traits::VertexIndices;
	using CellIndices   = Traits::CellIndices;


private:
	const Edges& m_edges;
	const Index m_index;
	
public:
	Edge( const Edges&, Index );
	
	auto edges() const -> const Edges&;

private:
	auto meshImp        () const -> const Traits::MeshType&;
	auto indexImp       () const -> Index;

	auto normalImp      () const -> NormalVector;
	auto lengthImp      () const -> scalar;
	auto verticesImp    () const -> VertexIndices;
	auto midpointImp    () const -> Vector2s;
	auto intersectionImp() const -> Vector2s;
	auto isBoundaryImp  () const -> bool;

	auto cellsImp     (Index) const -> CellIndices;
	auto domainCellImp(Index) const -> Index;
	auto ghostCellImp (Index) const -> Index;

	friend EdgeBase;
	friend Mesh;
};

} // end namespace hms

#endif